# @Time : 2024-10-16 16:10
# @Author : Fioman 
# @Phone : 13149920693
"""
1. 数字类型(Numeric Types)
    1) int (整数)
    2) float (浮点数)
    3) complex (复数)
"""
import sys

intA = 10
floatB = 3.14
complexC = 1 + 2j
# type返回的是这个对象是什么类型,比如下面的返回值分别为:
# <class 'int'> <class 'float'> <class 'complex'>
typeA, typeB, typeC = type(intA), type(floatB), type(complexC)
print(f"typeA: {typeA},typeB:{typeB},typeC:{typeC}")
# 然后我们看下typeA的类型又是什么类型呢,是type类型
print(f"type(typeA)= {type(typeA)}")

"""
这里要思考一下typeA的类型也就是<class,int>这个类型为什么是type类型
 注意一点就是在Python中所有的类型都是type类的实例,也就是说int,float,complex等类型都是
 type类型的实例. type(typeA) == type(int)
 """

"""
instance() 和 type()的区别?
1) type() 返回对象的类型,只检查对象的直接类型,不考虑继承关系
2) isinstance(obj,classinfo) 用于检测一个对象是否是某一个类或者元组中任意一个类的实例
    考虑到继承关系,并且可以可以检查多个类,但是classinfo只能是类类型,不是是具体的实例对象
"""


class Animal:
    pass


class Dog(Animal):
    pass


# 注意这样有问题的,type(Dog) 的类型是type
print(type(Dog))  # <class 'type'>
print(type(Dog) is Dog)  # False
print(type(Dog) is Animal)  # False

dog = Dog()
print(type(dog))  # <class 'Dog'>
print(type(dog) is Dog)  # True
print(type(dog) is Animal)  # False

# isinstance的用法
print(isinstance(dog, Dog))  # True
print(isinstance(dog, Animal))  # True
print(isinstance(Dog, type))  # True
# 这里只所以返回False,是因为isinstance()检查的是前面的对象是否是后面类型的一个实例
# 明显Dog是type类型的一个实例,而不是Dog类型本身的一个实例,所以上面返回True,下面
# 返回False
print(isinstance(Dog, Dog))  # False

# 2. 字符串类型(string)
s1 = "Fioman"
s2 = 'GeMeng'
print(type(s1), type(s2))

# 3. 序列类型
myList = [1, 2, 3, 'four', 5]
myTuple = (1, 2, 3, 4, 5)
print(type(myList), type(myTuple))

# 4. 映射类型
myDict = {
    "name": "Fioman",
    "age": 30
}
print(type(myDict))

# 5. 集合类型
mySet = {1, 2, 3, 4, 5}
myFrozenSet = frozenset([1, 2, 3])
print(type(mySet), type(myFrozenSet))

# 6. 布尔类型(boolean)
isActive = False
isLogin = True
print(type(isActive), type(isLogin))

# 7. None类型
myVal = None
print(type(myVal))

# 8. 数据类型的转换: 将一种数据类型转换为另外一种数据类型
# 1. int()
# 精度问题,从float转换为int,会丢弃到小数部分,而不是四舍五入
numFloat = 3.51
numInt = int(numFloat)
print(f"numInt = {numInt}")  # 3
# 如何实现四舍五入转换为int类型呢,可以加一个0.5再转换
numInt = int(numFloat + 0.5)
print(f"numInt = {numInt}")
# 转换失败,字符串转换为int的时候,如果非法就会报错
# strVal = "102a"
# strInt = int(strVal) # 报错 invalid literal for int() with base 0 '102a'
# print(f"strInt = {strInt}")

# 2. float()
# 整型到float
numInt = 100
numFloat = float(numInt)
print("numFloat: ", numFloat)
# 字符串到float
strVal = "102.333"
strFloat = float(strVal)
print(f"strFloat = {strFloat}")

# 3. str() 其他类型转换为字符串
numInt = 123
numStr = str(numInt)  # "123"
numFloat = 3.14
floatStr = str(numFloat)  # "3.14"
myList = [1, 2, 3, 4]
listStr = str(myList)  # '[1,2,3,4]'可以将一切类型都转换为字符串进行输出
print(numStr, floatStr, listStr)

# 4. list() 将其他科迭代对象转换为列表
strdata = "Fioman"
listData = list(strdata)
print("listData From Str: ", listData)  # ['F', 'i', 'o', 'm', 'a', 'n']

tupleData = (1, 2, 3, 4, 5)
listData = list(tupleData)
print("listData From tuple: ", listData)  # [1, 2, 3, 4, 5]

dictData = {
    "name": "Fioman",
    "age": 30
}
listData = list(dictData)
print("listData From dict: ", listData)  # ['name','age']
listData = list(dictData.keys())  # 和上面的一样,都是只转换键
print("listData From dict keys: ", listData)  # ['name', 'age']
listData = list(dictData.values())
print("listData From dict values: ", listData)  # ['Fioman', 30]
# 如果传入的不是可以迭代的类型,将引发TypeError错误
# intData = 123
# listData = list(intData)  # 报错 TypeError: 'int' object is not iterable
# print(f"listData From intData: {listData},引发错误")

# 5. set() 将其他可迭代类型转换为集合,去除重复元素
listData = [1, 2, 2, 3, 4, 5, 4, 3]
setData = set(listData)
print(f"setData from listData: {setData}")  # {1, 2, 3, 4, 5}
strData = "Hello"
setData = set(strData)
print(f"setData From strData: {setData}")  # {'l', 'H', 'o', 'e'}
# 注意,集合是无序的,因此转换后元素的顺序可能会发生改变,如果传入的对象是不可迭代的引发TypeError异常

# region 6. tuple() 将其他可迭代对象转换为元组
listData = [1, 2, 3, 4]
tupleData = tuple(listData)
print(f"tupleData From listData: {tupleData}")  # (1, 2, 3, 4)
strData = "Hello"
tupleData = tuple(strData)
print(f"tupleData From strData: {tupleData}")  # ('H', 'e', 'l', 'l', 'o')
# 注意: 传入的对象如果是不可以迭代的,引发TypeError异常
#           元组是不可变的,转换后无法修改元组中的元素
# endregion


# 7. dict() 将其他的可迭代类型转换为字典,通常用于从键值对的元组或者其他可迭代对象创建字典
# 1. 将列表的元组转换为字典,要求转换的对象必须是包含两个元素的元组
listOfTuples = [("a", 1), ("b", 2), ("c", 3)]
dictData = dict(listOfTuples)
print(f"dictData From listOfTuples: {dictData}")  # {'a': 1, 'b': 2, 'c': 3}
# 2.使用关键字参数来创建字典,通过dict()函数
dictData = dict(a=1, b=2, c=3)
print(f"dictData From keyword args: {dictData}")  # {'a': 1, 'b': 2, 'c': 3}
# 3. 使用zip函数结合dict()函数可以将两个可迭代对象合并为一个字典
keys = ["a", "b", "c"]
values = [1, 2, 3]
dictData = dict(zip(keys, values))
print(f"dictData From keys and values and zip: {dictData}")  # {'a': 1, 'b': 2, 'c': 3}

# 8. bytes() 和 bytearray
# bytes()将一个字符串或者是列表转换为一个字节对象.什么是字节对象,一个字节是8位,可以表示为0~255
# 之间的数字. 而编码的意思就是按照ASCII或者是UTF-8的方式使用固定的字节来表示不同的字符
print(bytes('A', 'utf-8'))  # 当传入的参数是字符串的时候,需要指定编码方式,因为不同的编码方式不一样
print(bytes([65, 66, 67]))  # 当传入的是整数序列的时候,不需要,因为它可以将整数直接转换为字节
print(bytes())  # 创建空字节对象
print(bytes(3))  # 创建3个零字节 b'\x00\x00\x00'

# bytearray是bytes的可变版本,将字符串或者是可迭代对象转换为可变的字节数组
strData = "hello"
bytearrayData = bytearray(strData, "utf-8")  # bytearray(b'hello')
print(f"bytearrayData From strData: {bytearrayData}")
intArrayData = [65, 66, 67]
bytearrayData = bytearray(intArrayData)  # bytearray(b'ABC')
print(f"bytearrayData From intArrayData: {bytearrayData}")
bytearrayData = bytearray()  # bytearray(b'')
print("bytearrayData From bytearrayData: ", bytearrayData)
bytearrayData = bytearray(5)  # bytearray(b'\x00\x00\x00\x00\x00')
print("bytearrayData From bytearrayData: ", bytearrayData)
# 修改字节数组中的元素
# bytearrayData[0] = 300 # 错误,只能是0~255之间的整数
bytearrayData[0] = 1  # \x01
bytearrayData[1] = 255  # \xff
bytearrayData[2] = 65  # A
print(f"bytearrayData From bytearrayData: {bytearrayData}")

# 9. frozenset() 将可迭代对象转换为不可变集合(集合可以去重)
listData = [1, 2, 3, 4, 5, 1, 2, 3]
frozenSetData = frozenset(listData)
print(f"frozenSetData From listData: {frozenSetData}")  # frozenset({1, 2, 3, 4, 5})
# 10. bin() 将一个整数转换为二进制字符串. 然后这里要解释一下什么是大端模式,什么是小端模式
# 大端模式和小端模式   大端和小端 可以这么去理解就是以什么作为开端
# 大端模式: 就是这个数据的存储以大的部分(即高位)放到了前面(低地址),怎么理解高位呢,比如一个整数
#  0x12345678     地址0x01  0x12(高位放到低地址),它的存储顺序是 0x12 0x34 0x56 0x78
# 小端模式: 就是这个数据的存储以小的部分(即低位)放到了前面(低地址)
# 0x12345678   0x01 0x78 (低位放到低地址)  0x78 0x56 0x34 0x12
# Python中一般是小端模式,我开发过的zbasic编程使用的就是大端模式
print(f"本系统采用的大小端模式: {sys.byteorder}")
# 将整数转换为二进制
binData = bin(10)  # 0b1010
print(f"binData from intData:{binData}")
# 去除掉前面的0b只保留转换后的数据
binData = bin(20)[2:]  # 10100
print(f"binData from intData:{binData}")

# region 1. 补充 不可变数据类型 number(数字) | bool(布尔) | string(字符串) | tuple(元组)
# 不可变数据类型: 数据所代表的变量指向的内存位置的值不能更改,就是不能就地修改值,如果要修改,需要重新
# 创建一个变量,重新开辟内存来存储新的值,不能直接在原来指向的内存位置进行修改

# 可以使用0x 0X 0o 0O 来表示16进制和8进制数据
decNumber = 123
hexNumber = 0x123
hexNumber2 = 0X123
octNumber = 0o123
octNumber2 = 0O123
print(decNumber, hexNumber, hexNumber2, octNumber, octNumber2)

# endregion

# region 2. 补充 可变数据类型 list(列表) | set(集合) | dict(字典)
# 可变数据类型: 数据所代表的变量指向的内存位置的值可以被修改,就是可以就地修改值,而不用创建
# 新的变量,也不用开辟新的内存来存储新的值
# endregion

# region 3. 进制说明和转换 bin() | oct() | int() | hex()
numberDec = 100
numberBin = bin(numberDec)
numberOct = oct(numberDec)
numberDec = int(numberDec)
numberHex = hex(numberDec)
print(numberBin, type(numberBin))  # 转换为二进制 0b1100100 <class ,'str'>
print(numberOct, type(numberOct))  # 转换为8进制 0o144 <class 'str'>
print(numberDec, type(numberDec))  # 转换为10进制 100 <class 'int'>
print(numberHex, type(numberHex))  # 转换为16进制 0x64 <class 'str'>

# 其他进制转换为十进制
number1 = int(str(numberBin), 2)
print("number1 = {}".format(number1))
number2 = int(str(numberOct), 8)
print("number2 = {}".format(number2))
number3 = int(str(numberHex), 16)
print("number3 = {}".format(number3))

# endregion
